#include "tchannel.h"

//#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef __linux__
#define printf_s printf
#define sprintf_s sprintf
#include <stdexcept>
#endif

#include "dtypedef.h"
#include "business_def.h"
#include "pfunc.h"
#include "luadisp.h"
#include "Log.h"

TranChannel::TranChannel(int tid_)
{
	BusinessDef *ptr_BDef = BusinessDef::getInstance();
	if(!ptr_BDef->getTranInfoByID(tid_,tatts))
	{
		CLogger::createInstance()->Log(MsgWarn,
			"TranChannel(%d) is not map atts config! [%s %s %d]"
			, tid_, __FILE__, __FUNCTION__, __LINE__);
	}
	char buf[128]={0};
	sprintf(buf,"%s[%d]_read_tran",tatts.name.c_str(),tatts.id);
	ReadDatas = new QueueData<ChannelCmd>(std::string(buf));
	sprintf(buf,"%s[%d]_write_tran",tatts.name.c_str(),tatts.id);
	WriteDataS = new QueueData<ChannelToTransmit>(std::string(buf));
	ToGchannelDatas = QueueDataSingle<TransmitToGChannel>::getInstance();
	ToGchannelDatas->setQueueDesc("To_Gchannel_queue");
	//获取采集信道匹配的协议配置
	if(!ptr_BDef->getProtocolInfoByTID(tid_,protodefs))
	{
		CLogger::createInstance()->Log(MsgWarn,
			"TranChannel(%d) is not map protocol config! [%s %s %d]"
			, tid_, __FILE__, __FUNCTION__, __LINE__);
	}
	//
	if(!ptr_BDef->getProtocolTypeByTID(tid_,protoType))
	{
		CLogger::createInstance()->Log(MsgWarn,
			"TranChannel(%d) is not define protocol type! [%s %s %d]"
			, tid_, __FILE__, __FUNCTION__, __LINE__);
	}
	this->initLua();
}


TranChannel::~TranChannel(void)
{
	releaseLua();
};

void TranChannel::add(ChannelToTransmit it)
{
	WriteDataS->add(it);
}

void TranChannel::initLua()
{
	if (1 == protoType)
	{
		//协议解析脚本
		luaScript = new luadisp();
		if (!luaScript->open(protodefs.luafile.c_str()))
		{
			CLogger::createInstance()->Log(MsgError,
				"open lua_script file %s  fail! [%s %s %d]", protodefs.luafile.c_str()
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	else {
		luaScript = NULL;
	}
};

void TranChannel::releaseLua()
{
	if (NULL != luaScript)
	{
		luaScript->close();
		delete luaScript;
		luaScript = NULL;
	}
};


int TranChannel::getBufferTran(unsigned char * buf, int size)
{
	int ret = -1;
	ChannelToTransmit it;
	if (WriteDataS->pop(it))
	{
		ret = getDownControlByLua(buf,size,it);
	}
	return ret;
};

int TranChannel::getDownControlByLua(unsigned char * buf,int size,ChannelToTransmit it)
{
	if (1 == protoType&&NULL != luaScript)
	{
		try {
			//you code for item data to cmd buf
			std::string _cmd = "";
			int checktype = 0;
			std::string _errormsg = "";
			memset(buf, 0, size);
			int len = 0;
			//生成16进制字符串命令
			//in this, the allYXVal is taskid to tran the server
			if (luaScript->getDownControl(pyfree::OnTran, it.pType, it.pID
				, static_cast<int>(it.val), _cmd, checktype, _errormsg,it.taskID) 
				&& !_cmd.empty())
			{
				if (it.changeF&&it.taskID>0) 
				{
					CLogger::createInstance()->Log(MsgInfo,
						"TaskID[%lu] and up_node[4] getDownControlByLua, time(%s),pID(%d),pType(%d),val(%.3f)"
						", CMD(%s),checktype(%d)"
						, it.taskID, pyfree::getCurrentTime().c_str()
						, it.pID, static_cast<int>(it.pType), it.val
						, _cmd.c_str(), checktype);
				}
				switch (checktype)
				{
				case 1://原字符串+crc校验
				{
					//转ACSII字符串
					len = pyfree::string2bytes(_cmd.c_str(), buf, static_cast<int>(_cmd.length()));
					//crc校验
					unsigned int crc = pyfree::crc16(buf, len);
					sprintf((char*)buf, "%s%02X%02X", _cmd.c_str(), (crc & 0XFF), ((crc >> 8) & 0XFF));
					len = (int)strlen((char*)buf);
					// _cmd = std::string((char*)buf);
					// len = static_cast<int>(_cmd.length());
				}
				break;
				case 2://ACSII字符串
				{
					len = pyfree::string2bytes(_cmd.c_str(), buf, static_cast<int>(_cmd.length()));
					//for (int j = 0; j < len; j++) {
					//	printf("%02X", buf[j]);
					//}
					//printf("\n");
					// _cmd = std::string((char*)buf, len);
				}
				break;
				default://不做改变
				{
					sprintf((char*)buf,"%s",_cmd.c_str());
					len = (int)strlen((char*)buf);
				}
				break;
				}
				return len;

			}
			else
			{
				char bufc[512] = { 0 };
				sprintf(bufc, "getDownControlByLua Error:exeType(%d),pID(%d),pType(%d),val(%.3f),errormsg(%s)"
					, static_cast<int>(pyfree::OnTran), it.pID, static_cast<int>(it.pType), it.val, _errormsg.c_str());
				#ifdef WIN32
				throw std::exception(bufc);
				#else
				throw std::logic_error(bufc);
				#endif
			}
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"getDownControlByLua for data to cmd error[%s]. [%s %s %d]"
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...)
		{
			CLogger::createInstance()->Log(MsgFatal,
				"getDownControlByLua for data to cmd error. [%s %s %d]"
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
}

int TranChannel::getResponseByLua(unsigned char *buf, int size, std::string info_desc
	, unsigned int respType/*=1*/, unsigned long taskID/*=0L*/,bool changeF/*=false*/)
{
	if (1 == protoType&&NULL != luaScript)
	{
		try {
			//you code for item data to cmd buf
			std::string _cmd = "";
			int checktype = 0;
			std::string _errormsg = "";
			memset(buf, 0, size);
			int len = 0;
			//生成16进制字符串命令
			//in this, the allYXVal is taskid to tran the server
			if (luaScript->getResponse(info_desc, _cmd, checktype, _errormsg, respType, taskID) 
				&& !_cmd.empty())
			{
				if (changeF&&taskID>0) 
				{
					CLogger::createInstance()->Log(MsgInfo,
						"TaskID[%lu] and up_node[4] getResponseByLua, info(%s)"
						", CMD(%s),checktype(%d)"
						, taskID, info_desc.c_str()
						, _cmd.c_str(), checktype);
				}
				// printf("cmd:%s\n",_cmd.c_str());
				switch (checktype)
				{
				case 1://crc
				{
					//转ACSII字符串
					len = pyfree::string2bytes(_cmd.c_str(), buf, static_cast<int>(_cmd.length()));
					//crc
					unsigned int crc = pyfree::crc16(buf, len);
					sprintf((char*)buf, "%s%02X%02X", _cmd.c_str(), (crc & 0XFF), ((crc >> 8) & 0XFF));
					len = (int)strlen((char*)buf);
					// _cmd = std::string((char*)buf);
					// len = static_cast<int>(_cmd.length());
				}
				break;
				case 2://ACSII
				{
					len = pyfree::string2bytes(_cmd.c_str(), buf, static_cast<int>(_cmd.length()));
					//for (int j = 0; j < len; j++) {
					//	printf("%02X", buf[j]);
					//}
					//printf("\n");
					// _cmd = std::string((char*)buf, len);
				}
				break;
				default://不做改变
				{
					sprintf((char*)buf,"%s",_cmd.c_str());
					len = (int)strlen((char*)buf);
				}
				break;
				}
				return len;

			}
			else
			{
				char bufc[512] = { 0 };
				sprintf(bufc, "getResponse Error:info(%s),errormsg(%s)"
					, info_desc.c_str(), _errormsg.c_str());
				#ifdef WIN32
				throw std::exception(bufc);
				#else
				throw std::logic_error(bufc);
				#endif
			}
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"getResponseByLua for data to cmd error[%s]. [%s %s %d]"
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...)
		{
			CLogger::createInstance()->Log(MsgFatal,
				"getResponseByLua for data to cmd error. [%s %s %d]"
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
}

int TranChannel::AddFrameTran(const unsigned char *buf, int len)
{
	int ret = AddFrameByLua(buf,len,*ToGchannelDatas);
	return ret;
}

int TranChannel::AddFrameByLua(const unsigned char *buf, int len,QueueData<TransmitToGChannel> &trans_)
{
	if (1 == protoType&&NULL != luaScript)
	{
		// printf("FrameByLua:%s\n",(char*)buf);
		try {
			std::string recs = "";
			std::string _errormsg = "";
			//转16进制字符串
			// char _buf[256] = { 0 };
			// int rlen = pyfree::bytes2string(buf, _buf, len);
			// std::string atres = std::string((char*)_buf);
			std::string atres = std::string((char*)buf);
			if (luaScript->getReciveIDVAL(atres.c_str(), recs, _errormsg))
			{
				// printf("recs:%s\n",(char*)recs.c_str());
				std::vector<std::string> _maps;
				if (pyfree::string_divide(_maps, recs, ";"))
				{
					int pID = 0;
					float Value = 0.0;
#ifdef WIN32
					pyfree::PType pType = pyfree::PType::PTDef;
					pyfree::ExeType exeType = pyfree::ExeType::ExeTDef;
#else
					pyfree::PType pType = pyfree::PTDef;
					pyfree::ExeType exeType = pyfree::ExeTDef;
#endif // WIN32
					unsigned long taskID = 0;
					for (size_t i = 0,mSize = _maps.size(); i < mSize; ++i)
					{
						std::vector<std::string> _map;
						if (pyfree::string_divide(_map, _maps[i], ",") && 5 == _map.size())
						{
							pID = atoi(_map[0].c_str());
							Value = static_cast<float>(atoi(_map[1].c_str()));
							pType = (pyfree::PType)atoi(_map[2].c_str());
							exeType = (pyfree::ExeType)atoi(_map[3].c_str());
							taskID = static_cast<unsigned long>(atol(_map[4].c_str()));
							//printf("id-val:%d,%.2f\n",_id,_val);
							trans_.add(TransmitToGChannel(exeType, pID, pType, Value, taskID));
						}
					}
				}
			}
			else {
				#ifdef WIN32
				throw std::exception(_errormsg.c_str());
				#else
				throw std::logic_error(_errormsg.c_str());
				#endif
			}
			return 1;
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"AddFrameByLua(%s,%d) func error[%s]. [%s %s %d]"
				, buf, len
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...) {
			CLogger::createInstance()->Log(MsgFatal,
				"AddFrameByLua(%s,%d) func error. [%s %s %d]"
				, buf, len
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
}